#ifndef __EQUATION2D_H__
#define __EQUATION2D_H__

#include <valarray>
#include <functional>
#include <iostream>
#include <cmath>
#include "Equation.h"

typedef std::valarray<double> Vector;

double f2D(double x, double y);
double u2D(double x, double y);
const Vector GetBoundary(int n, std::function<double(double x, double y)> _u = u2D);

class SymmetricTridiagonal2D
{
protected:
	int n;
	double diag;
	double alpha;

public:
	SymmetricTridiagonal2D(int _n);
	SymmetricTridiagonal2D(int _n, double d, double a);
	virtual ~SymmetricTridiagonal2D() = default;
	const Vector operator*(Vector& x) const;
	double GetDiag() const;
	double GetAlpha() const;
};

class PossionMatrix2D : public SymmetricTridiagonal2D
{
public:
	PossionMatrix2D(int _n);
	~PossionMatrix2D() = default;
};

class RHS2D
{
private:
	int n;
	Vector v;

public:
	RHS2D() = default;
	RHS2D(int _n, const Vector& boundary, std::function<double(double x, double y)> func = f2D);
	~RHS2D() = default;
	const Vector& GetVector() const;
	const int GetSize() const;
	double& operator[](std::size_t i);
};



class WeightedJacobi2D
{
private:
	int n;
	double omega;
	SymmetricTridiagonal2D T;
	Vector c;

public:
	WeightedJacobi2D(const PossionMatrix2D& A, const Vector& _f, double _omega = 2.0 / 3.0);
	~WeightedJacobi2D() = default;
	void IterateOnce(Vector& v) const;
};

#endif